package com.wzp.server;

import com.alibaba.fastjson.JSON;

import java.util.HashMap;
import java.util.Map;

/**
 * 两数之和
 *
 * @author zhengpeng.wang
 */
public class TwoSum {

    public static void main(String[] args) {
        int[] ints = new int[]{0, 1, 2, 3, 4};
        System.out.println(JSON.toJSONString(twoSum4(ints, 7)));
    }

    public static int[] twoSum2(int[] nums, int target) {
        for (int i = 0; i < nums.length; i++) {
            for (int j = i + 1; j < nums.length; j++) {
                if (nums[i] + nums[j] == target) {
                    return new int[]{i, j};
                }
            }
        }
        return new int[]{-1};
    }

    public static int[] twoSum3(int[] nums, int target) {
        Map<Integer, Integer> dumpMap = new HashMap<>();
        for (int i = 0; i < nums.length; i++) {
            if (dumpMap.containsKey(target - nums[i])) {
                return new int[]{dumpMap.get(target - nums[i]), i};
            }
            dumpMap.put(nums[i], i);
        }
        return new int[]{0};
    }



    public static int[] twoSum4(int[] nums, int target) {
//        for (int i = 0; i < nums.length; i++) {
//            for (int j = i + 1; j < nums.length; j++) {
//                if (nums[i] + nums[j] == target) {
//                    return new int[]{i, j};
//                }
//            }
//        }
//        return new int[]{-1};

        Map<Integer, Integer> seen = new HashMap<>();
        for (int i = 0; i < nums.length; i++) {
            if (seen.containsKey(target - nums[i])) {
                return new int[]{seen.get(target - nums[i]), i};
            }
            seen.put(nums[i], i);
        }
        return new int[]{-1};
    }

















    /**
     * 给定一个升序排列的整数数组 numbers ，从数组中找出两个数满足相加之和等于目标数 target 。
     * 假设每个输入只对应唯一的答案，而且不可以重复使用相同的元素。
     * 返回两数的下标值，以数组形式返回
     * 暴力解法
     * 时间复杂度：O(N的平方)
     * 空间复杂度：O(1)
     */
    public int[] twoSum(int[] nums, int target) {
        int n = nums.length;
        for (int i = 0; i < n; ++i) {
            for (int j = i + 1; j < n; ++j) {
                if (nums[i] + nums[j] == target) {
                    return new int[]{i, j};
                }
            }
        }
        return new int[0];
    }

    /**
     * 哈希表：将数组的值作为key存入map，target -num作为key
     * <p>
     * 时间复杂度： O(N)
     * <p>
     * 空间复杂度： O(N)
     */
    public int[] twoSum1(int[] nums, int target) {
        Map<Integer, Integer> map = new HashMap<Integer, Integer>();
        for (int i = 0; i < nums.length; ++i) {
            if (map.containsKey(target - nums[i])) {
                return new int[]{map.get(target - nums[i]), i};
            }
            map.put(nums[i], i);
        }
        return new int[0];
    }

    /**
     * 解法一：二分查找
     * 先固定一个值(从下标0开始)，再用二分查找查另外一个值，找不到则固定值向右移动，继续二分查找
     * <p>
     * 时间复杂度：O(N *logN)
     * <p>
     * 空间复杂度：O(1)
     */
    public int[] twoSearch(int[] numbers, int target) {
        for (int i = 0; i < numbers.length; ++i) {
            int low = i, high = numbers.length - 1;
            while (low <= high) {
                int mid = (high - low) / 2 + low;
                if (numbers[mid] == target - numbers[i]) {
                    return new int[]{i, mid};
                } else if (numbers[mid] > target - numbers[i]) {
                    high = mid - 1;
                } else {
                    low = mid + 1;
                }
            }
        }
        return null;
    }

    /**
     * 解法二：双指针
     * 左指针指向数组head，右指针指向数组tail，head+tail > target 则tail左移，否则head右移
     * <p>
     * 时间复杂度：O(N)
     * <p>
     * 空间复杂度：O(1)
     */
    public int[] twoPoint(int[] numbers, int target) {
        int low = 0, high = numbers.length - 1;
        while (low < high) {
            int sum = numbers[low] + numbers[high];
            if (sum == target) {
                return new int[]{low + 1, high + 1};
            } else if (sum < target) {
                ++low;

            } else {
                --high;
            }
        }
        return new int[]{-1, -1};
    }
}
